package UIFree
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.SecurityDomain;
	
	public class uif_app extends uif_component {
		private var _styles: uif_styles;
		private var _hintComponent: uif_component;
		public static const HINT_OVER: String = 'hint_over';
		public static const HINT_OUT: String = 'hint_out';
		public static const TIMEOUT: String = 'TIMEOUT';
		
		private static var _instance: uif_app;
		private var _context: LoaderContext;
		
		public static function instance(): uif_app {
			return _instance;
		}
		
		override public function get appstage(): EventDispatcher {
			return stage;
		}
		
		
		public function get loaderContext(): LoaderContext {
			return _context;
		}
		
		protected function createLoaderContent(): LoaderContext {
			return new LoaderContext(true);
		}
		
		public function uif_app(a_styles: uif_styles = null) {
			_instance = this;
			super(null);
			_context = createLoaderContent();
			
			_hintComponent = null;
			if (a_styles != null)
			 	_styles = a_styles;
			else _styles = new uif_styles();
			defStyles();
/*			this.addEventListener(MouseEvent.MOUSE_MOVE, function(e: MouseEvent): void {
				if (_hintComponent && !_hintComponent.hitTestPoint(root.mouseX, root.mouseY)) {
					var event: MouseEvent = new MouseEvent(HINT_OUT);  
					_hintComponent.dispatchEvent(event);
					_hintComponent = null;
				}
			});*/
			
			function getHintComponent(target: Object): uif_component {
				if (target) {
					if ((target is uif_component) && target.hint && !target.disable) return target as uif_component;
					else if (target.parent) return getHintComponent(target.parent);
				}
				return null;
			}
			
			this.addEventListener(MouseEvent.MOUSE_OVER, function(e: MouseEvent): void {
				var hc: uif_component = getHintComponent(e.target);
				if (hc && (_hintComponent != hc)) {
					
					if (_hintComponent != null) unFocus();
					_hintComponent = hc;
					_hintComponent.dispatchEvent(new MouseEvent(HINT_OVER));
					_hintComponent.addEventListener(MouseEvent.MOUSE_OUT, unFocus);
				}
			});	
			
			this.addEventListener(Event.REMOVED, function(e: Event): void {
				if (_hintComponent == e.target) unFocus();
			});
			
			this.addEventListener(TIMEOUT, doTimeOut);

		}	
		
		protected function doTimeOut(e: ObjectEvent): void {
		}
		
		private function unFocus(e: MouseEvent = null): void {
			_hintComponent.removeEventListener(MouseEvent.MOUSE_OUT, unFocus);
			_hintComponent.dispatchEvent(new MouseEvent(HINT_OUT));
			_hintComponent = null;
		}
		
		public function get classes(): Object {
			return {};
		}
		
		public function merge(styleName: String, addStyle: Object): Object {
			return union(styles[styleName], addStyle);
		}
		
		private function defStyles(): void {
			_styles.white = {
				fill_color: 0xFFFFFF,
				fill_alpha: 1
			}

			_styles.black = {
				fill_color: 0,
				fill_alpha: 1
			}

			_styles.red = {
				fill_color: 0xFF0000,
				fill_alpha: 1
			}

			_styles.green = {
				fill_color: 0x00FF00,
				fill_alpha: 1
			}
			
			_styles.blue = {
				fill_color: 0x0000FF,
				fill_alpha: 1
			}

			_styles.gray = {
				fill_color: 0x888888,
				fill_alpha: 1
			}

		}
		
		public function get styles(): uif_styles {
			return _styles;
		}
		
		protected function defaultStyle(): Object {
			return {fill_color: 0xFFFFFF, line_color: 0x444555};
		}
		
		public function styleByName(styleName: String): Object {
			if (_styles[styleName]) return _styles[styleName];
			else return defaultStyle();		
		}

		public function styleByObj(styleObj: Object): Object {
			if (styleObj is String) return styleByName(styleObj as String);
			else return styleObj;
		}
		
		public function getStyleInnerSpace(styleObj: Object): Number {
			var _result: Number = 0;
			var _style: Object = styleByObj(styleObj);
			if (_style.hasOwnProperty('padding'))
				_result += _style['padding'];
			if (_style.hasOwnProperty('line_width'))
				_result += _style['line_width'];
			return _result;
		}
		
		public function getStyleSpace(styleObj: Object, inner: Boolean = true): Number {
			var _result: Number = 0;
			var _style: Object = styleByObj(styleObj);
			if (_style.hasOwnProperty('margin'))
				_result += _style['margin'];
			if (inner) _result += getStyleInnerSpace(_style);
			return _result;			
		}
	}
}